package com.easylinkin.linkappapi.progress.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.additional.update.impl.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.bases.redis.util.RedisUtil;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.easylinkin.linkappapi.common.service.CommonService;
import com.easylinkin.linkappapi.common.utils.io.OutputStreamUtil;
import com.easylinkin.linkappapi.progress.entity.*;
import com.easylinkin.linkappapi.progress.entity.dto.ProgressInfoWarnDTO;
import com.easylinkin.linkappapi.progress.entity.dto.ProgressWarnExportDTO;
import com.easylinkin.linkappapi.progress.entity.vo.CalProgressWarnVo;
import com.easylinkin.linkappapi.progress.entity.vo.ProgressWarnVo;
import com.easylinkin.linkappapi.progress.mapper.*;
import com.easylinkin.linkappapi.progress.service.ProgressWarnService;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import com.easylinkin.linkappapi.tenant.entity.LinkappTenant;
import com.easylinkin.linkappapi.tenant.mapper.LinkappTenantMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import site.morn.rest.RestBuilders;
import site.morn.rest.RestMessage;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * ProgressWarn表服务实现类
 *
 * @author zhengwen
 * @date 2023/11/22
 */
@Slf4j
@Service("appProgressWarnService")
public class ProgressWarnServiceImpl extends ServiceImpl
        <ProgressWarnMapper, ProgressWarn> implements ProgressWarnService {
    @Resource
    private CommonService commonService;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private LinkappUserContextProducer linkappUserContextProducer;

    @Resource
    private ProgressInfoMapper progressInfoMapper;

    @Resource
    private ProgressLagInfoMapper progressLagInfoMapper;

    @Resource
    private ProgressRealDetailMapper progressRealDetailMapper;

    @Resource
    private ProgressWarnConfigMapper progressWarnConfigMapper;

    @Resource
    private LinkappTenantMapper linkappTenantMapper;

    @Override
    public boolean removeById(Serializable id) {
        return super.update().set("deleted_", id).eq("id_", id).update();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByIds(List<Long> idList) {
        // 将删除状态改为主键值
        new LambdaUpdateChainWrapper<>(getBaseMapper()).setSql("deleted_ = id_").in(ProgressWarn::getId, idList).update();
        return true;
    }


    @Override
    public boolean saveOne(ProgressWarn appProgressWarn) {
        commonService.setCreateAndModifyInfo(appProgressWarn);

        validParamRequired(appProgressWarn);
        validRepeat(appProgressWarn);
        validParamFormat(appProgressWarn);
        return save(appProgressWarn);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateOne(ProgressWarn appProgressWarn) {
        Assert.notNull(appProgressWarn.getId(), "id不能为空");
        commonService.setModifyInfo(appProgressWarn);

        validRepeat(appProgressWarn);
        validParamFormat(appProgressWarn);
        return updateById(appProgressWarn);
    }

    @Override
    public IPage<ProgressWarn> selectPage(Page page, ProgressWarn appProgressWarn) {
        return baseMapper.selectPage(page, appProgressWarn);
    }

    @Override
    public void export(ProgressWarn appProgressWarn, HttpServletRequest request, HttpServletResponse
            response) {

    }

    @Override
    public RestMessage calProgressWarn(CalProgressWarnVo calVo) {
        Integer type = calVo.getType();
        Integer dataType = calVo.getDataType();
        if (type == null || dataType == null) {
            return RestBuilders.errorBuilder().message("参数错误").build();
        }
        RestMessage restMessage = null;
        switch (type) {
            case 1:
                //新增
                restMessage = addProgressData(calVo);
                break;
            case 2:
                //修改
                restMessage = updateProgressData(calVo);
                break;
            case 3:
                //删除
                restMessage = delProgressWarnDelete(calVo);
                break;
            default:
                break;
        }

        return restMessage;
    }

    private RestMessage delProgressWarnDelete(CalProgressWarnVo calVo) {
        Integer dataType = calVo.getDataType();
        if (dataType == null) {
            return RestBuilders.errorBuilder().message("参数错误").build();
        }
        switch (dataType) {
            case 1:
                //TODO 删除配置，还计算给屁，应该考虑的是是否删除以前的计算？
                break;
            case 2:
                //删除实际进度详情，重新计算进度预警
                Object detail = calVo.getOldData();
                Assert.notNull(detail, "实际进度详情为空");
                ProgressRealDetail realDetail = (ProgressRealDetail) detail;
                Long progressTaskId = realDetail.getProgressTaskId();
                Assert.notNull(progressTaskId, "进度任务id为空");
                ProgressInfo progressInfo = progressInfoMapper.selectById(progressTaskId);
                Assert.notNull(progressInfo, "进度任务不存在");
                if (progressInfo.getType() == 2) {
                    //计划任务才需要重新计算
                    //查询最新配置
                    String tenantId = progressInfo.getTenantId();
                    ProgressWarnConfig warnConfig = queryConfigByTenantId(tenantId);
                    Assert.notNull(warnConfig, "进度预警配置不存在");
                    calVo.setNewData(warnConfig);
                    return configChangeAllWarnNewCal(calVo);
                }
                break;
            case 3:
                //删除进度计划任务（子节点），重新计算进度预警
                Object progress = calVo.getOldData();
                Assert.notNull(progress, "进度任务为空");
                ProgressInfo progressInfo1 = (ProgressInfo) progress;
                if (progressInfo1.getType() == 2) {
                    //计划任务才需要重新计算
                    //查询最新配置
                    String tenantId = progressInfo1.getTenantId();
                    ProgressWarnConfig warnConfig = queryConfigByTenantId(tenantId);
                    Assert.notNull(warnConfig, "进度预警配置不存在");
                    calVo.setNewData(warnConfig);
                    return configChangeAllWarnNewCal(calVo);
                }
                break;
            default:
                break;
        }
        return RestBuilders.successBuilder().build();
    }

    private RestMessage updateProgressData(CalProgressWarnVo calVo) {
        //都暴力的一刀切，重新计算吧，懒得分析范围
        Integer dataType = calVo.getDataType();
        if (dataType == null) {
            return RestBuilders.errorBuilder().message("参数错误").build();
        }
        switch (dataType) {
            case 1:
                //修改配置,如果修改了值才重新计算
                Object newData = calVo.getNewData();
                Object oldData = calVo.getOldData();
                if (newData instanceof ProgressWarnConfig && oldData instanceof ProgressWarnConfig) {
                    ProgressWarnConfig newConfig = (ProgressWarnConfig) newData;
                    ProgressWarnConfig oldConfig = (ProgressWarnConfig) oldData;
                    if (newConfig.getFinishLess().equals(oldConfig.getFinishLess())
                            && newConfig.getFinishMore().equals(oldConfig.getFinishMore())
                            && newConfig.getUndoneLess().equals(oldConfig.getUndoneLess())
                            && newConfig.getUndoneMore().equals(oldConfig.getUndoneMore())
                            && newConfig.getParentFinishLess().equals(oldConfig.getParentFinishLess())
                            && newConfig.getParentFinishMore().equals(oldConfig.getParentFinishMore())
                            && newConfig.getParentUndoneLess().equals(oldConfig.getParentUndoneLess())
                            && newConfig.getParentUndoneMore().equals(oldConfig.getParentUndoneMore())) {
                    } else {
                        //有一个不匹配就重新计算
                        return configChangeAllWarnNewCal(calVo);
                    }
                }
                break;
            case 2:
                //修改实际进度详情，改了实际开始、结束时间、百分比
                Object newData1 = calVo.getNewData();
                Object oldData1 = calVo.getOldData();
                ProgressRealDetail newDetail = (ProgressRealDetail) newData1;
                ProgressRealDetail oldDetail = (ProgressRealDetail) oldData1;
                if (newDetail.getRealStartTime().equals(oldDetail.getRealStartTime())
                        && newDetail.getRealEndTime().equals(oldDetail.getRealEndTime())
                        && newDetail.getPercentage().equals(oldDetail.getPercentage())) {
                    //有一个不匹配就重新计算
                } else {
                    Long progressTaskId = newDetail.getProgressTaskId();
                    Assert.notNull(progressTaskId, "进度任务id为空");
                    ProgressInfo progressInfo = progressInfoMapper.selectById(progressTaskId);
                    Assert.notNull(progressInfo, "进度任务不存在");
                    if (progressInfo.getType() == 2) {
                        //计划任务才需要重新计算
                        //查询最新配置
                        String tenantId = progressInfo.getTenantId();
                        ProgressWarnConfig warnConfig = queryConfigByTenantId(tenantId);
                        Assert.notNull(warnConfig, "进度预警配置不存在");
                        calVo.setNewData(warnConfig);
                        return configChangeAllWarnNewCal(calVo);
                    }
                }
                break;
            case 3:
                //修改进度计划任务（子节点），改了计划开始、结束时间、工期
                Object newData2 = calVo.getNewData();
                Object oldData2 = calVo.getOldData();
                ProgressInfo newProgress = (ProgressInfo) newData2;
                ProgressInfo oldProgress = (ProgressInfo) oldData2;
                if (newProgress.getStartTime().equals(oldProgress.getStartTime())
                        && newProgress.getEndTime().equals(oldProgress.getEndTime())
                        && newProgress.getTotalWork().equals(oldProgress.getTotalWork())) {
                    //有一个不匹配就重新计算
                } else {
                    if (newProgress.getType() == 2) {
                        //计划任务才需要重新计算
                        //查询最新配置
                        String tenantId = newProgress.getTenantId();
                        ProgressWarnConfig warnConfig = queryConfigByTenantId(tenantId);
                        Assert.notNull(warnConfig, "进度预警配置不存在");
                        calVo.setNewData(warnConfig);
                        return configChangeAllWarnNewCal(calVo);
                    }
                    return RestBuilders.successBuilder().build();
                }
                break;
            default:
                break;
        }
        return RestBuilders.successBuilder().build();
    }

    private RestMessage addProgressData(CalProgressWarnVo calVo) {
        //都暴力的一刀切，重新计算吧，懒得分析范围
        Integer dataType = calVo.getDataType();
        if (dataType == null) {
            return RestBuilders.errorBuilder().message("参数错误").build();
        }
        switch (dataType) {
            case 1:
                //新增配置，全部重算
                return configChangeAllWarnNewCal(calVo);
            case 2:
                //新增实际进度详情，重新计算进度预警
                Object detail = calVo.getNewData();
                Assert.notNull(detail, "实际进度详情为空");
                if (detail instanceof ProgressRealDetail) {
                    ProgressRealDetail realDetail = (ProgressRealDetail) detail;
                    Long progressTaskId = realDetail.getProgressTaskId();
                    Assert.notNull(progressTaskId, "进度任务id为空");
                    ProgressInfo progressInfo = progressInfoMapper.selectById(progressTaskId);
                    Assert.notNull(progressInfo, "进度任务不存在");
                    if (progressInfo.getType() == 2) {
                        //计划任务才需要重新计算
                        //查询最新配置
                        String tenantId = progressInfo.getTenantId();
                        ProgressWarnConfig warnConfig = queryConfigByTenantId(tenantId);
                        Assert.notNull(warnConfig, "进度预警配置不存在");
                        calVo.setNewData(warnConfig);
                        return configChangeAllWarnNewCal(calVo);
                    }
                } else {
                    return RestBuilders.failureMessage().setMessage("参数异常：新增数据不是进度详情");
                }
                break;
            case 3:
                //新增进度计划任务（子节点），重新计算进度预警
                Object progress = calVo.getNewData();
                Assert.notNull(progress, "进度任务为空");
                if (progress instanceof ProgressInfo) {
                    ProgressInfo progressInfo1 = (ProgressInfo) progress;
                    if (progressInfo1.getType() == 2) {
                        //计划任务才需要重新计算
                        //查询最新配置
                        String tenantId = progressInfo1.getTenantId();
                        ProgressWarnConfig warnConfig = queryConfigByTenantId(tenantId);
                        Assert.notNull(warnConfig, "进度预警配置不存在");
                        calVo.setNewData(warnConfig);
                        return configChangeAllWarnNewCal(calVo);
                    }
                } else {
                    return RestBuilders.failureMessage().setMessage("参数异常：新增数据不是进度任务");
                }
                break;
            default:
                break;
        }
        return RestBuilders.successBuilder().build();
    }

    private ProgressWarnConfig queryConfigByTenantId(String tenantId) {
        QueryWrapper<ProgressWarnConfig> qw = new QueryWrapper<>();
        qw.eq("tenant_id_", tenantId);
        qw.orderByDesc("create_time_");
        qw.last("limit 1");
        ProgressWarnConfig progressWarnConfig = progressWarnConfigMapper.selectOne(qw);
        //如果为空就给默认配置
        if (progressWarnConfig == null) {
            progressWarnConfig = initDefaultWarnConfig(tenantId);
        }

        return progressWarnConfig;
    }

    /**
     * 初始化默认配置
     *
     * @param tenantId 租户id
     * @return 默认配置
     */
    private ProgressWarnConfig initDefaultWarnConfig(String tenantId) {
        if (StringUtils.isNotBlank(tenantId)) {
            ProgressWarnConfig warnConfig = new ProgressWarnConfig();
            warnConfig.setTenantId(tenantId);
            warnConfig.setFinishLess(-5);
            warnConfig.setFinishMore(5);
            warnConfig.setUndoneLess(-5);
            warnConfig.setUndoneMore(5);
            warnConfig.setParentFinishLess(-5);
            warnConfig.setParentFinishMore(5);
            warnConfig.setParentUndoneLess(-5);
            warnConfig.setParentUndoneMore(5);
            //commonService.setCreateAndModifyInfo(warnConfig);
            //progressWarnConfigMapper.insert(warnConfig);
            return warnConfig;
        }
        return null;
    }

    private RestMessage configChangeAllWarnNewCal(CalProgressWarnVo calVo) {
        //重新计算所有进度预警
        //1、取配置信息
        Object progressWarnConfig = calVo.getNewData();
        if (progressWarnConfig instanceof ProgressWarnConfig) {
            ProgressWarnConfig warnConfig = (ProgressWarnConfig) progressWarnConfig;
            String tenantId = warnConfig.getTenantId();
            //TODO 增加计算缓存
            String key = "progressWarnCal:" + tenantId;
            //暂时设置为5分钟（兜底）
            redisUtil.expire(key, 5 * 60);
            //2、查询租户下所有计划任务
            List<ProgressInfo> progressPlanList = queryTenantAllProgressList(tenantId);
            if (CollectionUtil.isNotEmpty(progressPlanList)) {
                //3、计划任务list的id转list
                List<Long> progressIdList = progressPlanList.stream().map(ProgressInfo::getId).collect(Collectors.toList());
                //4、删除配置租户下的所有进度预警
                delProgressWarnBy(progressIdList);
                //5、任务组织成树
                List<Tree<Long>> progressTreeList = transProgressToTree(progressPlanList);
                //6、查询实际进度详情，按id分组
                Map<Long, List<ProgressRealDetail>> realDetailMap = queryRealDetailGroupById(progressIdList);
                //7、迭代树，计算每个节点的预警（迭代）
                Date now = new Date();
                Map<Long, ProgressWarn> warnMap = new HashMap<>();
                Map<Long, List<Long>> childMap = new HashMap<>();
                itCalWarnData(progressTreeList, warnConfig, realDetailMap, warnMap, childMap, now);
            }
            //计算完成，删除缓存
            redisUtil.del(key);
        }

        return RestBuilders.successBuilder().build();
    }

    /**
     * 查询进度详情根据进度任务id分组
     *
     * @param progressIdList 进度任务id
     * @return 进度详情根据进度任务id分组map
     */
    private Map<Long, List<ProgressRealDetail>> queryRealDetailGroupById(List<Long> progressIdList) {
        Map<Long, List<ProgressRealDetail>> realDetailMap = new HashMap<>();
        QueryWrapper<ProgressRealDetail> progressRealDetailQw = new QueryWrapper<>();
        progressRealDetailQw.in("progress_task_id_", progressIdList);
        List<ProgressRealDetail> progressRealDetailList = progressRealDetailMapper.selectList(progressRealDetailQw);
        if (CollectionUtil.isNotEmpty(progressRealDetailList)) {
            realDetailMap = progressRealDetailList.stream().collect(Collectors.groupingBy(ProgressRealDetail::getProgressTaskId));
        }
        return realDetailMap;
    }

    /**
     * 迭代计算预警数据
     *
     * @param progressTreeList 进度任务树数据
     * @param warnConfig       预警配置
     * @param realDetailMap    实际进度详情map
     * @param warnMap          预警map
     * @param childMap         子集map
     * @param now
     */
    private void itCalWarnData(List<Tree<Long>> progressTreeList, ProgressWarnConfig warnConfig, Map<Long, List<ProgressRealDetail>> realDetailMap, Map<Long, ProgressWarn> warnMap, Map<Long, List<Long>> childMap, Date now) {
        if (CollectionUtil.isNotEmpty(progressTreeList)) {

            for (Tree<Long> tree : progressTreeList) {
                ProgressInfo progressInfo = (ProgressInfo) tree.get("progressInfo");
                if (progressInfo != null && progressInfo.getId() != 0) {
                    List<Tree<Long>> children = tree.getChildren();
                    if (CollectionUtil.isNotEmpty(children)) {
                        List<Long> childIdList = children.stream().map(Tree::getId).collect(Collectors.toList());
                        childMap.put(progressInfo.getId(), childIdList);
                        itCalWarnData(children, warnConfig, realDetailMap, warnMap, childMap, now);

                        //再计算父级进度预警
                        if (progressInfo.getType() == 2) {
                            ProgressWarn parentWarn = calParentWarnData(progressInfo, warnConfig, childMap, warnMap);
                            if (parentWarn != null) {
                                commonService.setCreateAndModifyInfo(parentWarn);
                                baseMapper.insert(parentWarn);
                                warnMap.put(progressInfo.getId(), parentWarn);
                            }
                        }
                    } else {
                        //计算进度预警
                        /* 找bug用的
                        if (progressInfo.getId() == 171){
                            log.info("debug");
                        }*/
                        if (progressInfo.getType() == 2) {
                            ProgressWarn warn = calWarnData(progressInfo, warnConfig, realDetailMap, now);
                            commonService.setCreateAndModifyInfo(warn);
                            baseMapper.insert(warn);
                            warnMap.put(progressInfo.getId(), warn);
                        }
                    }
                }
            }
        }
    }

    /**
     * 计算父级预警数据
     *
     * @param progressInfo 进度任务信息
     * @param warnConfig   预警配置
     * @param childMap     子集map
     * @param warnMap      预警map
     * @return 预警信息
     */
    private ProgressWarn calParentWarnData(ProgressInfo progressInfo, ProgressWarnConfig warnConfig, Map<Long, List<Long>> childMap, Map<Long, ProgressWarn> warnMap) {
        if (CollectionUtil.isEmpty(warnMap)) {
            return null;
        }

        ProgressWarn progressWarn = new ProgressWarn();
        progressWarn.setProgressId(progressInfo.getId());
        progressWarn.setPlanWorkDay(progressInfo.getTotalWork());
        progressWarn.setRealPercentage(0d);

        //子级任务id
        List<Long> childIdList = childMap.get(progressInfo.getId());

        //1、父级预警配置
        Integer parentFinishLess = warnConfig.getParentFinishLess();
        Integer parentFinishMore = warnConfig.getParentFinishMore();
        Integer parentUndoneLess = warnConfig.getParentUndoneLess();
        Integer parentUndoneMore = warnConfig.getParentUndoneMore();

        //2、父级任务的子级任务的预警信息
        List<ProgressWarn> childWarnList = childIdList.stream().map(warnMap::get).collect(Collectors.toList());

        /* 找bug用的
        Long prId = progressInfo.getId();
        if (prId == 155){
            log.info("debug");
        }*/
        if (CollectionUtil.isNotEmpty(childWarnList)) {
            //3、最早开始时间、最晚开始时间
            //childWarnList排除realStartTime为空的，再取最早开始时间
            Date realStartTime = childWarnList.stream().map(ProgressWarn::getRealStartTime).filter(Objects::nonNull).min(Date::compareTo).orElse(null);
            Date realEndTime = childWarnList.stream().map(ProgressWarn::getRealEndTime).filter(Objects::nonNull).max(Date::compareTo).orElse(null);
            //log.info("任务:id:{},名称:{},realStartTime:{},realEndTime:{}",progressInfo.getId(),progressInfo.getName(), DateUtil.formatDateTime(realStartTime), DateUtil.formatDateTime(realEndTime));
            progressWarn.setRealStartTime(realStartTime);
            progressWarn.setRealEndTime(realEndTime);

            //4、实际进度:(各子级计划工期*实际完成百分比累加)/各子级的计划工期累加
            double realPercentage = childWarnList.stream().mapToDouble(warn -> {
                Integer planWorkDay = warn.getPlanWorkDay();
                Double percentage = warn.getRealPercentage();
                return planWorkDay * percentage;
            }).sum() / childWarnList.stream().mapToInt(ProgressWarn::getPlanWorkDay).sum();

            progressWarn.setRealPercentage(NumberUtil.round(realPercentage, 4).doubleValue());

            //5、子集是否有应开始未开始的任务
            boolean hasUndone = childWarnList.stream().anyMatch(warn -> {
                Integer startState = warn.getStartState();
                return startState != null && startState == 2;
            });
            if (hasUndone) {
                progressWarn.setStartState(2);
                progressWarn.setWarnState(3);
            } else {
                //6、实际结束日期与计划结束日期差值为N
                if (realEndTime != null) {
                    //long btDay = DateUtil.betweenDay(realEndTime, progressInfo.getEndTime(), true) + 1;

                    Long btDay = getBetweenDay(realEndTime, progressInfo.getEndTime(), progressInfo);

                    //5、实际进度完成百分比
                    int completePercentage = NumberUtil.compare(realPercentage, 100D);
                    if (completePercentage >= 0) {
                        //实际进度完成百分比>=100%，预警状态为正常
                        if (btDay < parentFinishLess) {
                            //实际结束日期与计划结束日期差值在预警下限前，预警状态为提前
                            progressWarn.setWarnState(1);
                        }
                        if (parentFinishLess <= btDay && btDay <= parentFinishMore) {
                            //实际结束日期与计划结束日期差值在预警范围内，预警状态为正常
                            progressWarn.setWarnState(2);
                        }
                        if (btDay > parentFinishMore) {
                            //实际结束日期与计划结束日期差值不在预警范围内，预警状态为滞后
                            progressWarn.setWarnState(3);
                        }
                    } else {
                        //实际进度完成百分比<100%，预警状态为滞后
                        if (btDay < parentUndoneLess) {
                            //实际结束日期与计划结束日期差值在预警下限前，预警状态为提前
                            progressWarn.setWarnState(1);
                        }
                        if (parentUndoneLess <= btDay && btDay <= parentUndoneMore) {
                            //实际结束日期与计划结束日期差值在预警范围内，预警状态为正常
                            progressWarn.setWarnState(2);
                        }
                        if (btDay > parentUndoneMore) {
                            //实际结束日期与计划结束日期差值不在预警范围内，预警状态为滞后
                            progressWarn.setWarnState(3);
                        }
                    }
                }
            }

        }

        return progressWarn;
    }

    /**
     * 末级计算进度预警
     *
     * @param progressInfo  进度计划
     * @param warnConfig    预警配置
     * @param realDetailMap 实际进度详情
     * @param now
     * @return 进度预警
     */
    private ProgressWarn calWarnData(ProgressInfo progressInfo, ProgressWarnConfig warnConfig, Map<Long, List<ProgressRealDetail>> realDetailMap, Date now) {
        ProgressWarn progressWarn = new ProgressWarn();
        progressWarn.setProgressId(progressInfo.getId());
        progressWarn.setPlanWorkDay(progressInfo.getTotalWork());
        progressWarn.setRealPercentage(0d);

        //末级任务，计算进度预警
        //1、查询进度计划的实际进度
        List<ProgressRealDetail> realDetailList = realDetailMap.get(progressInfo.getId());
        if (CollectionUtil.isNotEmpty(realDetailList)) {
            //realDetailList找出最早的开始时间，最晚的结束时间
            Date realStartTime = realDetailList.stream().map(ProgressRealDetail::getRealStartTime).min(Date::compareTo).orElse(null);
            Date realEndTime = realDetailList.stream().map(ProgressRealDetail::getRealEndTime).max(Date::compareTo).orElse(null);
            progressWarn.setRealStartTime(realStartTime);
            progressWarn.setRealEndTime(realEndTime);

            //2、实际进度求和
            Double realPercentage = realDetailList.stream().mapToDouble(ProgressRealDetail::getPercentage).sum();
            progressWarn.setRealPercentage(realPercentage);

            //3、获取末级预警上下限
            Integer finishLess = warnConfig.getFinishLess();
            Integer finishMore = warnConfig.getFinishMore();
            Integer undoneLess = warnConfig.getUndoneLess();
            Integer undoneMore = warnConfig.getUndoneMore();

            Date planEndTime = progressInfo.getEndTime();

            //4、实际结束日期与计划结束日期差值为N
            Long btDay = getBetweenDay(realEndTime, planEndTime, progressInfo);

            //5、实际进度完成百分比
            int completePercentage = NumberUtil.compare(realPercentage, 100D);
            if (completePercentage >= 0) {
                //有实际进度详情，进行中
                progressWarn.setStartState(3);
                //实际进度完成百分比>=100%，预警状态为正常
                if (btDay < finishLess) {
                    //实际结束日期与计划结束日期差值在预警下限前，预警状态为提前
                    progressWarn.setWarnState(1);
                }
                if (finishLess <= btDay && btDay <= finishMore) {
                    //实际结束日期与计划结束日期差值在预警范围内，预警状态为正常
                    progressWarn.setWarnState(2);
                }
                if (btDay > finishMore) {
                    //实际结束日期与计划结束日期差值不在预警范围内，预警状态为滞后
                    progressWarn.setWarnState(3);
                }
            } else {
                //实际进度完成百分比<100%，预警状态为滞后
                //有实际进度详情，已完成
                progressWarn.setStartState(4);
                if (btDay < undoneLess) {
                    //实际结束日期与计划结束日期差值在预警下限前，预警状态为提前
                    progressWarn.setWarnState(1);
                }
                if (undoneLess <= btDay && btDay <= undoneMore) {
                    //实际结束日期与计划结束日期差值在预警范围内，预警状态为正常
                    progressWarn.setWarnState(2);
                }
                if (btDay > undoneMore) {
                    //实际结束日期与计划结束日期差值不在预警范围内，预警状态为滞后
                    progressWarn.setWarnState(3);
                }
            }
        } else {
            //任务没有进度详情，在应开始任务在计划开始日期未开始,直接就是有进度风险,(计划开始时间最后一秒比较)
            Date planStartTime = DateUtil.endOfDay(progressInfo.getStartTime());
            if (now.before(planStartTime)) {
                //未开始
                progressWarn.setStartState(1);
            }
            if (now.after(planStartTime)) {
                //应开始未开始
                progressWarn.setStartState(2);
                //当前时间已经在计划时间之后，有进度风险
                progressWarn.setWarnState(3);
            }

        }

        return progressWarn;
    }

    /**
     * 获取实际结束日与计划结束日期相差天数
     *
     * @param realEndTime  实际结束日期
     * @param planEndTime  计划结束日期
     * @param progressInfo 进度计划
     * @return 相差天数
     */
    private Long getBetweenDay(Date realEndTime, Date planEndTime, ProgressInfo progressInfo) {
        if (realEndTime == null || planEndTime == null) {
            return 0L;
        }
        Date startOfDay = DateUtil.beginOfDay(realEndTime);
        Date endOfDay = DateUtil.beginOfDay(planEndTime);
        log.info("id:{}时间realEndTime:{},planEndTime:{}", progressInfo.getId(), DateUtil.format(startOfDay, DatePattern.NORM_DATE_FORMAT), DateUtil.format(endOfDay, DatePattern.NORM_DATE_FORMAT));
        //Long btDay = DateUtil.between(startOfDay, endOfDay, DateUnit.DAY, true) + 1;
        //不包含当天
        Long btDay = DateUtil.between(startOfDay, endOfDay, DateUnit.DAY, true);
        if (startOfDay.before(endOfDay)) {
            btDay = -btDay;
        }
        return btDay;
    }

    /**
     * 转换进度计划任务数据为树
     *
     * @param progressPlanList 进度计划任务list
     * @return 进度树
     */
    private List<Tree<Long>> transProgressToTree(List<ProgressInfo> progressPlanList) {
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        treeNodeConfig.setIdKey("id");
        treeNodeConfig.setWeightKey("createTime");
        Long rootId = 0L;
        List<Tree<Long>> treeList = TreeUtil.build(progressPlanList, rootId, treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId());
                    tree.setParentId(treeNode.getParentId());
                    tree.setName(treeNode.getName());
                    tree.setWeight(treeNode.getCreateTime());
                    tree.putExtra("progressInfo", treeNode);
                });
        return treeList;
    }

    /**
     * 删除预警
     *
     * @param progressIdList 进度任务id集合
     */
    private void delProgressWarnBy(List<Long> progressIdList) {
        if (CollectionUtil.isNotEmpty(progressIdList)) {
            QueryWrapper<ProgressWarn> progressWarnQw = new QueryWrapper<>();
            progressWarnQw.in("progress_id_", progressIdList);
            baseMapper.delete(progressWarnQw);
        }
    }

    /**
     * 查询租户进度任务数据
     *
     * @param tenantId 租户id
     * @return 进度任务数据list
     */
    private List<ProgressInfo> queryTenantAllProgressList(String tenantId) {
        QueryWrapper<ProgressInfo> progressQw = new QueryWrapper<>();
        progressQw.eq("tenant_id_", tenantId);
        List<ProgressInfo> progressList = progressInfoMapper.selectList(progressQw);
        return progressList;
    }

    @Override
    public RestMessage selectDtoPage(Page page, ProgressWarnVo progressWarnVo) {
        ProgressInfo progressInfo = progressWarnVo.getProgressInfo();
        Assert.notNull(progressInfo, "进度计划信息为空");
        Long progressInfoId = progressInfo.getId();
//        Assert.notNull(progressInfoId, "进度计划id为空");

        String tenantId = progressInfo.getTenantId();

        String key = "progressWarnCal:" + tenantId;
        boolean calIng = redisUtil.hasKey(key);
        if (calIng) {
            return RestBuilders.errorBuilder().message("正在计算中，请稍后再试").build();
        }

        //查询进度计划信息
//        ProgressInfo progressPlan = progressInfoMapper.getOneById(progressInfoId);
        ProgressInfo progressPlan = null;

        if (progressInfoId == null){
            //查询总计划
            LambdaQueryWrapper<ProgressInfo> progressQw = new LambdaQueryWrapper<>();
            progressQw.eq(ProgressInfo::getTenantId, linkappUserContextProducer.getNotNullCurrent().getTenantId());
            progressQw.eq(ProgressInfo::getName, progressInfo.getName());
            List<ProgressInfo> progressInfos = progressInfoMapper.selectList(progressQw);
            if (CollectionUtil.isNotEmpty(progressInfos)){
                progressPlan = progressInfos.get(0);
            }
        }else {
            progressPlan = progressInfoMapper.selectById(progressInfo.getId());
//            Assert.notNull(progressPlan, "进度计划不存在");
        }

        if (progressPlan != null) {
            progressInfo.setParentIds(progressPlan.getParentIds() + progressPlan.getId() + ",");
            progressWarnVo.setProgressInfo(progressInfo);
        }else {
            return RestBuilders.errorBuilder().data(new ArrayList<>()).build();
        }
        IPage<ProgressInfoWarnDTO> record = baseMapper.selectDtoPage(page, progressWarnVo);
        //判断滞后或提前天数
        record.getRecords().forEach(r -> {
            //判断预警状态
            ProgressWarn progressWarn = r.getProgressWarn();
            if (progressWarn != null){
                if (Integer.valueOf(1).equals(progressWarn.getWarnState())){
                    //提前
                    //计算提前天数
                    Date realEndTime = progressWarn.getRealEndTime();
                    Date endTime = r.getEndTime();
                    if (realEndTime != null && endTime != null){
                        progressWarn.setWarnDay(DateUtil.betweenDay(realEndTime, endTime, true));
                    }
                }else if (Integer.valueOf(3).equals(progressWarn.getWarnState())){
                    //判断是否未开始
                    if (Integer.valueOf(1).equals(progressWarn.getStartState()) || Integer.valueOf(2).equals(progressWarn.getStartState())){
                        //滞后
                        //计算滞后天数
                        Date realStartTime = progressWarn.getRealStartTime();
                        if (null == realStartTime){
                            realStartTime = new Date();
                        }
                        Date startTime = r.getStartTime();
                        if (startTime != null){
                            progressWarn.setWarnDay(DateUtil.betweenDay(realStartTime, startTime, true));
                        }
                    }else{
                        Date realEndTime = progressWarn.getRealEndTime();
                        if (null == realEndTime){
                            realEndTime = new Date();
                        }
                        Date endTime = r.getEndTime();
                        progressWarn.setWarnDay(DateUtil.betweenDay(endTime, realEndTime, true));
                    }
                }
            }
        });
        return RestBuilders.successBuilder().data(record).build();
    }

    @Override
    public RestMessage getLagInfo(Long progressTaskId) {
        //查询进度任务滞后信息
        ProgressLagInfo progressLagInfo = progressLagInfoMapper.getOneByProgressId(progressTaskId);

        return RestBuilders.successBuilder().data(progressLagInfo).build();
    }

    @Override
    public RestMessage saveOrUpdateLagInfo(ProgressLagInfo progressLagInfo) {
        Long id = progressLagInfo.getId();
        if (id == null) {
            //新增
            commonService.setCreateAndModifyInfo(progressLagInfo);
            progressLagInfoMapper.insert(progressLagInfo);
        } else {
            //修改
            commonService.setModifyInfo(progressLagInfo);
            progressLagInfoMapper.updateById(progressLagInfo);
        }
        return RestBuilders.successBuilder().build();
    }

    @Override
    public List<ProgressWarnExportDTO> selectProgressWarnDtoTreeList(RequestModel<ProgressWarnVo> requestModel) {
        //TODO 查询进度预警数据
        return null;
    }

    @Override
    public RestMessage manualCalProgressWarn(CalProgressWarnVo calProgressWarnVo) {
        //获取当前用户
        LinkappUser linkappUser = linkappUserContextProducer.getCurrent();
        Assert.notNull(linkappUser, "用户信息为空");
        String tenantId = linkappUser.getTenantId();
        Assert.notNull(tenantId, "租户id为空");
        //查询最新配置
        ProgressWarnConfig warnConfig = queryConfigByTenantId(tenantId);
        Assert.notNull(warnConfig, "进度预警配置不存在");
        calProgressWarnVo.setType(1);
        calProgressWarnVo.setDataType(1);
        calProgressWarnVo.setNewData(warnConfig);
        return configChangeAllWarnNewCal(calProgressWarnVo);
    }

    @Override
    public void exportAll(RequestModel<ProgressWarnVo> requestModel, HttpServletRequest request, HttpServletResponse response) throws Exception {
        Page page = new Page();
        page.setCurrent(1);
        page.setSize(-1);
        ProgressWarnVo progressWarnVo = requestModel.getCustomQueryParams();
        ProgressInfo progressInfo = progressWarnVo.getProgressInfo();
        Assert.notNull(progressInfo, "进度计划信息为空");
        Long progressInfoId = progressInfo.getId();
        //查询进度计划信息
        ProgressInfo progressPlan = progressInfoMapper.getOneById(progressInfoId);
        if (progressPlan != null) {
            progressInfo.setParentIds(progressPlan.getParentIds() + progressInfo.getId() + ",");
            progressWarnVo.setProgressInfo(progressInfo);
        }
        IPage<ProgressInfoWarnDTO> record = baseMapper.selectDtoPage(page, progressWarnVo);

        List<ProgressInfoWarnDTO> list = record.getRecords();

        //ProgressInfoWarnDTO progressInfoWarnDTO = new ProgressInfoWarnDTO();
        //BeanUtil.copyProperties(progressPlan, progressInfoWarnDTO, CopyOptions.create().ignoreNullValue());
        //list.add(progressInfoWarnDTO);
        //progressInfoId = 0L;
        //progressInfoId = 0L;

        //获取类型
        String keyValue = "计划任务项:name,计划开始时间:startTimeStr,计划结束时间:endTimeStr,计划工期:totalWork,实际完成百分比:percentageStr,实际开始时间:realStartTimeStr,实际结束时间:realEndTimeStr,前置任务:beforeWork,预警状态:warnStateName,滞后原因:lagReasonStateName";
        String title = "进度预警";
        String fileName = title + ".xlsx";
        // 创建工作簿对象
        Workbook workbook = new XSSFWorkbook();
        // 创建工作表对象
        Sheet sheet = workbook.createSheet("Sheet1");
        //设置表头
        Row row = sheet.createRow(0);
        String keyValues[] = keyValue.split(",");
        int cellNum;
        if (ArrayUtil.isNotEmpty(keyValues)) {
            cellNum = keyValues.length;
            for (int i = 0; i < cellNum; i++) {
                String[] keyAndValue = keyValues[i].split(":");
                if (ArrayUtil.isNotEmpty(keyAndValue)) {
                    Cell nameCell = row.createCell(i);
                    nameCell.setCellValue(keyAndValue[0]);
                }
            }
        } else {
            cellNum = 0;
        }

        //行数据处理
        if (CollectionUtil.isNotEmpty(list)) {
            List<Tree<Long>> treeList = transProgressWarnDtoToTree(list, progressInfoId);
            Integer startRow = 1;
            if (CollectionUtil.isNotEmpty(treeList)) {
                Map<Long, Integer> rowNumMap = new HashMap<>();
                rowNumMap.put(progressInfoId, 1);

                //迭代生成excel行
                Integer index = itMakeExcelRow(treeList, sheet, startRow, cellNum, rowNumMap);
                //设置折叠展开
                sheet.setRowGroupCollapsed(index - 1, false);
            }
        }

        // 导出Excel文件
        OutputStream outputStream = OutputStreamUtil.getOutputStream(request, response, fileName);
        workbook.write(outputStream);
        response.flushBuffer();
        workbook.close();
        outputStream.close();
    }

    /**
     * 转换进度预警数据为树
     *
     * @param list           进度预警数据
     * @param progressInfoId 进度计划id
     * @return 进度预警数据树
     */
    private List<Tree<Long>> transProgressWarnDtoToTree(List<ProgressInfoWarnDTO> list, Long progressInfoId) {
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        treeNodeConfig.setIdKey("id");
        treeNodeConfig.setWeightKey("createTime");
        Long rootId = progressInfoId;
        List<Tree<Long>> treeList = TreeUtil.build(list, rootId, treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId());
                    tree.setParentId(treeNode.getParentId());
                    tree.setName(treeNode.getName());
                    tree.setWeight(treeNode.getCreateTime());
                    ProgressWarnExportDTO warnExportDTO = convertProgressWarnExportDTO(treeNode);
                    tree.putExtra("progressWarnExportDTO", warnExportDTO);
                });
        return treeList;
    }

    /**
     * 转换进度预警数据为导出数据对象
     *
     * @param warnDTO 进度预警数据
     * @return 导出数据对象
     */
    private ProgressWarnExportDTO convertProgressWarnExportDTO(ProgressInfoWarnDTO warnDTO) {
        ProgressWarnExportDTO dto = new ProgressWarnExportDTO();
        dto.setName(warnDTO.getName());
        dto.setCreateTime(warnDTO.getCreateTime());
        Date startTime = warnDTO.getStartTime();
        if (startTime != null) {
            String startTimeStr = DateUtil.format(startTime, DatePattern.NORM_DATE_FORMAT);
            dto.setStartTimeStr(startTimeStr);
        }
        Date endTime = warnDTO.getEndTime();
        if (endTime != null) {
            String endTimeStr = DateUtil.format(endTime, DatePattern.NORM_DATE_FORMAT);
            dto.setEndTimeStr(endTimeStr);
        }

        dto.setTotalWork(warnDTO.getTotalWork());
        ProgressWarn warn = warnDTO.getProgressWarn();
        if (warn != null) {
            Double realPercentage = warn.getRealPercentage();
            if (realPercentage != null) {
                realPercentage = NumberUtil.round(realPercentage, 2).doubleValue();
                dto.setPercentageStr(realPercentage + "%");
            }
            Date realStartTime = warn.getRealStartTime();
            if (realStartTime != null) {
                String realStartTimeStr = DateUtil.format(realStartTime, DatePattern.NORM_DATE_FORMAT);
                dto.setRealStartTimeStr(realStartTimeStr);
            }
            Date realEndTime = warn.getRealEndTime();
            if (realEndTime != null) {
                String realEndTimeStr = DateUtil.format(realEndTime, DatePattern.NORM_DATE_FORMAT);
                dto.setRealEndTimeStr(realEndTimeStr);
            }
            Integer warnState = warn.getWarnState();
            String warnStateName = "";
            if (warnState != null) {
                switch (warnState) {
                    case 1:
                        warnStateName = "提前";
                        break;
                    case 2:
                        warnStateName = "正常";
                        break;
                    case 3:
                        warnStateName = "滞后";
                        break;
                    default:
                        break;
                }
            }
            //拼接天数
            if (null != warn.getWarnDay()){
                warnStateName += ("(" + warn.getWarnDay() + "天)");
            }
            dto.setWarnStateName(warnStateName);
        }
        dto.setBeforeWork(warnDTO.getBeforeWork());
        ProgressLagInfo lagInfo = warnDTO.getProgressLagInfo();
        if (lagInfo != null) {
            Integer lagReason = lagInfo.getReasonState();
            String lagReasonName = "";
            if (lagReason != null) {
                switch (lagReason) {
                    case 1:
                        lagReasonName = "天气环境原因";
                        break;
                    case 2:
                        lagReasonName = "人力原因";
                        break;
                    case 3:
                        lagReasonName = "材料原因";
                        break;
                    case 4:
                        lagReasonName = "机械原因";
                        break;
                    case 5:
                        lagReasonName = "政策性原因";
                        break;
                    case 6:
                        lagReasonName = "外部手续原因";
                        break;
                    case 7:
                        lagReasonName = "设计原因";
                        break;
                    case 8:
                        lagReasonName = "场地原因";
                        break;
                    case 9:
                        lagReasonName = "工作面原因";
                        break;
                    case 10:
                        lagReasonName = "其他";
                        break;
                    default:
                        break;
                }
            }
            dto.setLagReasonStateName(lagReasonName);
        }
        return dto;
    }

    /**
     * 递归生成excel行
     *
     * @param treeList 进度预警数据树
     * @param sheet    excel sheet
     * @param startRow 开始行
     * @param cellNum  单元格数量
     */
    private Integer itMakeExcelRow(List<Tree<Long>> treeList, Sheet sheet, Integer startRow, int cellNum, Map<Long, Integer> rowNumMap) {
        Integer finRow = startRow;
        if (CollectionUtil.isNotEmpty(treeList)) {
            int total = treeList.size();
            for (int r = total - 1; r >= 0; r--) {
                Tree<Long> tree = treeList.get(r);
                Integer rowNum = writeExcelData(tree, sheet, finRow, cellNum, rowNumMap);
                finRow = rowNum;

                List<Tree<Long>> children = tree.getChildren();
                if (CollectionUtil.isNotEmpty(children)) {
                    Long parentId = tree.getId();
                    //int childSize = children.size();

                    //迭代下级
                    Integer index = itMakeExcelRow(children, sheet, finRow, cellNum, rowNumMap);

                    //下级迭代完了，返回excel行数，设置层级分组、折叠
                    Integer oldParentRowNum = rowNumMap.get(parentId);
                    if (oldParentRowNum != null) {
                        log.info("总数据量{}-Excel行{}至{}行分组折叠", rowNumMap.size(), oldParentRowNum, index);

                        sheet.groupRow(oldParentRowNum, index);
                        //sheet.setRowGroupCollapsed(oldParentRowNum, false);
                    }

                    //最新rowNum
                    finRow = index;
                } else {
                    //没有子集了，设置分组?


                }
            }

        }
        return finRow;
    }

    /**
     * 写excel行数据
     *
     * @param tree      进度预警数据
     * @param sheet     excel sheet
     * @param rowNum    行号
     * @param cellNum   单元格数量
     * @param rowNumMap 数据行号map
     * @return 数据行号map
     */
    private Integer writeExcelData(Tree<Long> tree, Sheet sheet, Integer rowNum, int cellNum, Map<Long, Integer> rowNumMap) {
        ProgressWarnExportDTO progressWarnExportDTO = (ProgressWarnExportDTO) tree.get("progressWarnExportDTO");
        if (progressWarnExportDTO != null) {
            rowNumMap.put(tree.getId(), rowNum);
            Map<Integer, String> valMap = getExcelValMap(progressWarnExportDTO);
            Row row = sheet.createRow(rowNum);
            for (int i = 0; i < cellNum; i++) {
                if (ArrayUtil.isNotEmpty(valMap)) {
                    Cell nameCell = row.createCell(i);
                    nameCell.setCellValue(valMap.get(i));
                }
            }
            rowNum++;
        }
        return rowNum;
    }

    /**
     * 获取excel行数据map
     *
     * @param progressWarnExportDTO 进度预警数据
     * @return excel行数据map
     */
    private Map<Integer, String> getExcelValMap(ProgressWarnExportDTO progressWarnExportDTO) {
        Map<Integer, String> map = new HashMap<>();
        map.put(0, progressWarnExportDTO.getName());
        map.put(1, progressWarnExportDTO.getStartTimeStr());
        map.put(2, progressWarnExportDTO.getEndTimeStr());
        map.put(3, progressWarnExportDTO.getTotalWork() + "");
        map.put(4, progressWarnExportDTO.getPercentageStr());
        map.put(5, progressWarnExportDTO.getRealStartTimeStr());
        map.put(6, progressWarnExportDTO.getRealEndTimeStr());
        map.put(7, progressWarnExportDTO.getBeforeWork());
        map.put(8, progressWarnExportDTO.getWarnStateName());
        map.put(9, progressWarnExportDTO.getLagReasonStateName());
        return map;
    }


    @Override
    @Scheduled(cron = "1 0 0 * * ?")
    public void progressWarnCalJob() {
        log.info("计算进度告警定时任务执行开始");

        //查询所有租户
        List<LinkappTenant> tenantList = linkappTenantMapper.selectList(null);
        if (CollectionUtil.isNotEmpty(tenantList)) {
            for (LinkappTenant tenant : tenantList) {
                String tenantId = tenant.getId();
                //查询最新配置
                ProgressWarnConfig warnConfig = queryConfigByTenantId(tenantId);
                //Assert.notNull(warnConfig, "进度预警配置不存在");
                if (warnConfig != null){
                    CalProgressWarnVo calProgressWarnVo = new CalProgressWarnVo();
                    calProgressWarnVo.setType(1);
                    calProgressWarnVo.setDataType(1);
                    calProgressWarnVo.setNewData(warnConfig);
                    configChangeAllWarnNewCal(calProgressWarnVo);
                }
            }
        }
        log.info("计算进度告警定时任务执行结束");
    }


    @Override
    public ProgressWarn getOneById(Serializable id) {
        return baseMapper.getOneById(id);
    }

    /**
     * 校验重复
     */
    private void validRepeat(ProgressWarn appProgressWarn) {

        /* List<ProgressWarn> list = new LambdaQueryChainWrapper<>(baseMapper)
            .eq(ProgressWarn::getDeviceCode, appProgressWarn.getDeviceCode())
            .list();
            if (list.size() > 0 && (list.size() > 1 || ObjectUtils.isEmpty(appProgressWarn.getId()) || !appProgressWarn.getId().equals(list.get(0).getId()))) {
                throw new BusinessException("名称重复");
            }
        */


    }


    /**
     * 校验参数必填
     */
    private void validParamRequired(ProgressWarn appProgressWarn) {
        //Assert.notNull(appProgressWarn, "参数为空");
        //Assert.isTrue(StringUtils.isNotBlank(appProgressWarn.getName()), "名称为空");
    }

    /**
     * 校验参数格式
     */
    private void validParamFormat(ProgressWarn appProgressWarn) {
        //Assert.isTrue(appProgressWarn.getName() == null || appProgressWarn.getName().length() <= 50,
        //        "名称超长");
    }
}

